package com.sy.simpleegg.platform.kkb

import android.util.ArrayMap
import com.google.gson.reflect.TypeToken
import com.sy.simpleegg.constant.ProductType
import com.sy.simpleegg.ext.logFile
import com.sy.simpleegg.platform.kkb.bean.HeartResp
import com.sy.simpleegg.platform.kkb.bean.MqGetSettingData
import com.sy.simpleegg.platform.kkb.bean.KkbBuyPackageBean
import com.sy.simpleegg.platform.kkb.bean.KkbBuyPackageResp
import com.sy.simpleegg.platform.kkb.bean.KkbGoodBean
import com.sy.simpleegg.platform.kkb.bean.config.KkbGetPayCoinData
import com.sy.simpleegg.platform.kkb.bean.config.GetPayQrCodeData
import com.sy.simpleegg.platform.kkb.bean.good.GoodsCoinResponse
import com.sy.simpleegg.platform.kkb.bean.good.RechargeGoodsData
import com.sy.simpleegg.platform.kkb.bean.login.LoginToken
import com.sy.simpleegg.platform.kkb.bean.member.ConsumeCoinResult
import com.sy.simpleegg.platform.kkb.bean.member.GetMemberLoginQrCode
import com.sy.simpleegg.platform.kkb.bean.member.KkbOpenIdResponse
import com.sy.simpleegg.platform.kkb.bean.member.KkbQrCodeMemberInfoResponse
import com.sy.simpleegg.platform.kkb.bean.member.SaveCoinResult
import com.sy.simpleegg.platform.kkb.bean.pay.KkbChannelWaitOffData
import com.sy.simpleegg.platform.kkb.bean.pay.PayResult
import com.sy.simpleegg.platform.kkb.bean.pay.RepCashDataBean
import com.sy.simpleegg.platform.kkb.constant.Constant
import com.sy.simpleegg.platform.kkb.manager.KkbBusinessManager
import com.sy.simpleegg.platform.kkb.manager.KkbInitApiManager
import com.sy.simpleegg.platform.kkb.network.base.BaseResult
import com.sy.simpleegg.platform.kkb.network.base.IDeviceManager
import com.sy.simpleegg.platform.kkb.network.manager.DeviceManager
import com.sy.simpleegg.util.BigDecimalUtil
import com.sy.simpleegg.util.GsonUtil
import com.ych.ytdevicesdk.entity.AppInfoEntity
import io.reactivex.Observer
import io.reactivex.disposables.Disposable
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import org.json.JSONObject
import java.lang.Thread.sleep


class KkbClient(
    private val ssid: String,
    private val mainBoardNum: String,
    private val agreement: Int,
    private val agreementVer: String,
    private val devType: String,
    private val title: String,
    private val appSoftVer: Int,
    private val netIp: String,
    private val netMask: String,
    private val netGateWay: String,
    private val isTest: Boolean,
    private val kkbClientListener: KkbClientListener,
) {
    private var deviceManager: IDeviceManager? = null
    private var businessManager: KkbBusinessManager? = null

    private var devNum: String = mainBoardNum
    private var mchIdentity: String = ssid

    private var token = ""

    private var normalPackageList: MutableList<KkbGoodBean> = mutableListOf()
    private var rechargePackageList: MutableList<KkbGoodBean> = mutableListOf()
    private var defaultCoin = 1

    private var scope = MainScope()
    private var loopHeartJob: Job? = null
    private var loginJob: Job? = null
    private var loop = true
    private var loginLoop = true

    private var jobMap: ArrayMap<String, Job> = ArrayMap<String, Job>()

    private var heartInterval = 30 * 1000L

    private var extractCoinResult = -1//-1-处理中 0-成功 1-失败

    init {
        Constant.IS_TEST = isTest
        val appInfo = AppInfoEntity().apply {
            this.deviceType = devType
            this.appTitle = title
            this.softVer = appSoftVer
        }

        deviceManager = DeviceManager.singleInstance()
//        deviceManager = YchDeviceManager.get()
//        deviceManager?.initSdkNew(ssid, mainBoardNum, devType, agreement, agreementVer, appInfo)

        deviceManager?.setInitListener(object : IDeviceManager.InitListener {
            override fun registerFailed(errorCode: Long, errorMsg: String?) {
                logFile("KKB 注册失败 errorCode=$errorCode errorMsg=$errorMsg")
                kkbClientListener.registerFailed(errorCode, errorMsg)
            }

            override fun needUpdate(vararg updateAddress: String?) {
                logFile("KKB 需要更新：${GsonUtil.getInstance()?.toJson(updateAddress)}")
                kkbClientListener.needUpdate(*updateAddress)
            }

            override fun bindStatus(isSuccess: Boolean, deviceNumber: String?) {
                // 是否绑定 绑定成功后就可以进行业务系统的调用了
                // 绑定失败则需要去后台进行设备绑定到项目
                // deviceNumber 用于生成绑定设备二维码
                logFile("KKB ${if (isSuccess) "已绑定" else "未绑定"} 设备号：$deviceNumber")
                devNum = deviceNumber!!
                kkbClientListener.bindStatus(isSuccess, deviceNumber)
                devNum?.let {
                    if (isSuccess) {
                        initApi(appSoftVer, netIp, netMask, netGateWay, it)
                    }
                }
            }

            override fun onError(type: String?, errorCode: Long, msg: String?) {
                // type 类型指向 IDeviceManager.ErrorType
                logFile("KKB 设备报错：$type errorCode=$errorCode msg=$msg")
                kkbClientListener.onError(type, errorCode, msg)
            }
        })
        deviceManager?.setEventListener(object : IDeviceManager.IMqMessageListener {
            override fun deviceBinding() {
                logFile("KKB 设备绑定推送 设备号：$devNum")
                devNum?.let {
                    initApi(appSoftVer, netIp, netMask, netGateWay, it)
                    kkbClientListener.deviceBinding(it)
                }
            }

            override fun deviceUnBinding() {
                logFile("KKB 设备解绑")
                kkbClientListener.deviceUnBinding()
            }

            override fun deviceReBoot() {
                logFile("KKB 设备重启")
                kkbClientListener.deviceReBoot()
            }

            override fun extractCoin(dataJson: String?): Int {
                //{"Amount":2,"Money":1,"OrderID":"b1d50024-343e-64d1-daf9-10304b43bae4"}
                logFile("KKB 设备出币：$dataJson")
                dataJson?.let {
                    try {
                        val orderJson = JSONObject(it)
                        val coins = if (orderJson.has("Amount")) orderJson.getLong("Amount")
                            .toString() else "0"
                        val money =
                            if (orderJson.has("Money")) (orderJson.getLong("Money") * 100).toString() else "0"
                        val orderId =
                            if (orderJson.has("OrderID")) orderJson.getString("OrderID") else ""
                        kkbClientListener.extractCoin(true, coins, money, orderId)
                        extractCoinResult = -1
                        while (extractCoinResult == -1) {
                            sleep(1000L)
                        }

                    } catch (e: Exception) {
                        e.printStackTrace()
                        logFile("KKB 设备出币订单解析异常：${e.message}")
                    }
                }
                logFile("KKB 出币result=")
                return if (extractCoinResult == -1) 1 else extractCoinResult
            }

            override fun getDeviceSetting(dataJson: String?): Map<Int?, Any>? {
                logFile("KKB 获取服务器改变设备设置：$dataJson")
                val mqGetSettingData = GsonUtil.getInstance()?.fromJson<MqGetSettingData>(
                    dataJson,
                    object : TypeToken<MqGetSettingData?>() {}.type
                )
                kkbClientListener.getDeviceSetting(dataJson)
                return null
            }

            override fun setDeviceSetting(dataJson: String?): Int? {
                logFile("KKB 控制板上报了设置变更推送到服务器：$dataJson")
                kkbClientListener.setDeviceSetting(dataJson)
                return null
            }

            override fun changeCashPackage() {
                logFile("KKB 后台设置的现金套餐变化，推送到设备，设备需要拉取现金套餐")
                kkbClientListener.changeCashPackage()
            }

            override fun updateOrder(
                orderId: String?,
                transactionId: String?,
                deviceStatus: Int,
                remark: String?,
            ) {
                logFile("KKB 后台设置订单状态：orderId=$orderId transactionId=$transactionId deviceStatus=$deviceStatus remark=$remark")
                kkbClientListener.updateOrder(orderId, transactionId, deviceStatus, remark)
            }

            override fun deviceStatues(status: Int) {
                logFile("KKB 后台设置设备状态：$status")
                kkbClientListener.deviceStatues(status)
            }
        })

        deviceManager = DeviceManager.singleInstance()
            .initSdk(ssid, mainBoardNum, devType, agreement, agreementVer, appInfo)
//        deviceManager?.initSdkNew(ssid, mainBoardNum, devType, agreement, agreementVer, appInfo)

        businessManager = KkbBusinessManager.get()

        scope.launch {
            delay(3000)
            getNormalPackage()
        }
    }

    private fun initApi(
        appVer: Int,
        netIp: String,
        netMask: String,
        netGateWay: String,
        devNum: String,
    ) {
        deviceManager?.getMacId()?.let {
            KkbInitApiManager.get().initApi(
                appVer,
                netIp,
                netMask,
                netGateWay,
                devNum,
                it,
                object : KkbInitApiManager.InitListener {
                    override fun loginTokenData(loginToken: LoginToken) {
                        Constant.TOKEN = loginToken.Token
                        loopHeart()
                        kkbClientListener.loginComplete()
                    }
                })
        }
    }

    private fun loopHeart() {
        loopHeartJob?.cancel()

        loopHeartJob = scope.launch(Dispatchers.IO) {
            val interval = 1000L
            val overCount = 15
            var checkCount = 0
            var state = 0//0-开始请求 1-有响应 2-异常

            while (loop) {
                checkCount = 0
                state = 0

                val wifiStrength = (com.sy.simpleegg.constant.Constant.NETWORK_SIGNAL * 5).toString()
                val apMac = ""
                val mqOnline = if (Constant.MQONLINE) "1" else "0"

                businessManager?.heart(
                    "0",
                    wifiStrength,
                    apMac,
                    mqOnline,
                    object : Observer<BaseResult<HeartResp?>> {
                        override fun onSubscribe(d: Disposable) {
                            logFile("KKB 开始发送心跳")
                        }

                        override fun onError(e: Throwable) {
                            logFile("KKB 心跳异常：${e.message}")
                            state = 2
                            onComplete()
                        }

                        override fun onComplete() {
                            logFile("KKB 心跳结束")

                        }

                        override fun onNext(t: BaseResult<HeartResp?>) {
                            logFile(
                                "KKB 心跳完成：${
                                    GsonUtil.getInstance()?.toJson(t)
                                } ${BigDecimalUtil.scientificToPlainString(t.data!!.Time.toString())}"
                            )
                            state = 1
                        }
                    })

                while (state == 0) {
                    delay(interval)
                    checkCount++
                    if (checkCount >= overCount) {
                        //超时
                        state = 2
                    }
                }

                delay(heartInterval)
            }
        }
    }

    /**
     * 提交错误信息
     *
     * @param errorType 错误类型
     * @param errorMsg  错误数据
     */
    fun deviceErrorSubmit(errorType: Int, errorMsg: String) {
        deviceManager?.deviceErrorSubmit(errorType, errorMsg)
    }

    /**
     * 获取SDK版本
     *
     * @return 版本信息
     */
    fun getSdkVersion(): String {
        return deviceManager?.getSdkVersion() ?: ""
    }

    /**
     * 连接测试
     *
     * @param iConnectTestResponse 连接测试响应
     * @return {@link IDeviceManager}
     */
    fun connectTest(iConnectTestResponse: IDeviceManager.IConnectTestResponse): IDeviceManager? {
        return deviceManager?.connectTest(iConnectTestResponse)
    }

    /**
     * 调试器，是否开启调试模式
     *
     * @param isOpen     是否开启
     * @param useTestUrl 使用测试服务器
     * @return {@link IDeviceManager}
     */
    fun debugger(isOpen: Boolean, useTestUrl: Boolean): IDeviceManager? {
        return deviceManager?.debugger(isOpen, useTestUrl)
    }

    /**
     * 日志开关，是否开启日志输出
     *
     * @param isOpen 是否开启
     * @return {@link IDeviceManager}
     */
    fun logger(isOpen: Boolean): IDeviceManager? {
        return deviceManager?.logger(isOpen)
    }


    /**
     * 获取二维码
     * @param transactionId 事务id
     * @return 正扫二维码
     */
    fun getQrCode(transactionId: String) {
//        businessManager?.getQrCode(transactionId)
    }

    /**
     * 获取兑币套餐
     * @param type 1-普通套餐 2-充值套餐 3-所有套餐
     */
    fun getCoinPackage(type: Int) {
        when (type) {
            1 -> getNormalPackage()
            2 -> getRechargePackage()
            3 -> getAllPackage()
        }
    }

    /**
     * 获取商品列表
     *
     * @param observer 响应
     * @param <T>      设置类型
     */
    private fun getNormalPackage() {
        if (devNum.isNullOrEmpty() || mchIdentity.isNullOrEmpty()) return
        val paramMap: MutableMap<String?, Any> = mutableMapOf()
        paramMap["mchIdentity"] = mchIdentity!!
        paramMap["deviceCode"] = devNum!!

        scope.launch(Dispatchers.IO) {
            val interval = 1000L
            var result = -1//-1-请求中 0-请求完成 1-请求异常

            do {
                businessManager?.getPackageList(
                    paramMap,
                    object : Observer<BaseResult<GoodsCoinResponse?>> {

                        override fun onSubscribe(d: Disposable) {
                            logFile("KKB 开始获取普通套餐列表")
                            result = -1
                        }

                        override fun onNext(t: BaseResult<GoodsCoinResponse?>) {
                            logFile("KKB 普通套餐列表：${GsonUtil.getInstance()?.toJson(t)}")
                            t.data?.let { coinsData ->
                                coinsData.packageList.forEach { normalData ->
                                    normalPackageList.add(
                                        KkbGoodBean().apply {
                                            PackageType = 1
                                            PackageID = normalData.packageId.toString()
                                            PakageName = normalData.packageName
                                            Price = normalData.priceCent.toString()
                                            Coins = normalData.pearlCount
                                            Subscript = normalData.subscript ?: ""
                                        }
                                    )
                                }
                                defaultCoin = coinsData.pearlCountPerYuan
                                result = 0
                            }
                        }

                        override fun onError(throwable: Throwable) {
                            logFile("KKB 获取普通套餐异常：${throwable.message}")
                            result = 1
                        }

                        override fun onComplete() {
                            logFile("KKB 获取普通套餐结束")
                            kkbClientListener.updateCoinsPackage(normalPackageList)

                            kkbClientListener.updateConfig(
                                KkbGetPayCoinData(
                                    listOf(),
                                    0,
                                    0,
                                    0,
                                    defaultCoin,
                                    "",
                                    ""
                                )
                            )
                        }
                    })

                while (result == -1) {
                    delay(interval)
                }

                if (result != 0){
                    delay(3000)
                }
            } while (result != 0)
        }

//        businessManager?.getPackageList(
//            paramMap,
//            object : Observer<BaseResult<GoodsCoinResponse?>> {
//
//                override fun onSubscribe(d: Disposable) {
//                    logFile("KKB 开始获取普通套餐列表")
//                }
//
//                override fun onNext(t: BaseResult<GoodsCoinResponse?>) {
//                    logFile("KKB 普通套餐列表：${GsonUtil.getInstance()?.toJson(t)}")
//                    t.data?.let { coinsData ->
//                        coinsData.packageList.forEach { normalData ->
//                            normalPackageList.add(
//                                KkbGoodBean().apply {
//                                    PackageType = 1
//                                    PackageID = normalData.packageId.toString()
//                                    PakageName = normalData.packageName
//                                    Price = normalData.priceCent.toString()
//                                    Coins = normalData.pearlCount
//                                    Subscript = normalData.subscript ?: ""
//                                }
//                            )
//                        }
//                        defaultCoin = coinsData.pearlCountPerYuan
//                    }
//                }
//
//                override fun onError(throwable: Throwable) {
//                    logFile("KKB 获取普通套餐异常：${throwable.message}")
//
//                }
//
//                override fun onComplete() {
//                    logFile("KKB 获取普通套餐结束")
//                    kkbClientListener.updateCoinsPackage(normalPackageList)
//
//                    kkbClientListener.updateConfig(
//                        KkbGetPayCoinData(
//                            listOf(),
//                            0,
//                            0,
//                            0,
//                            defaultCoin,
//                            "",
//                            ""
//                        )
//                    )
//                }
//            })
    }

    /**
     * 获取充值套餐
     */
    private fun getRechargePackage() {
        devNum?.let {
            businessManager?.getRechargeList(it, object : Observer<BaseResult<RechargeGoodsData?>> {

                override fun onSubscribe(d: Disposable) {
                    logFile("KKB 开始获取充值套餐列表")
                }

                override fun onNext(t: BaseResult<RechargeGoodsData?>) {
                    logFile("KKB 充值套餐列表：${GsonUtil.getInstance()?.toJson(t)}")
                    t.data?.let { coinsData ->
                        coinsData.data.forEach { rechargeData ->
                            rechargePackageList.add(
                                KkbGoodBean().apply {
                                    PackageType = 2
                                    PackageID = rechargeData.iD
                                    PakageName = rechargeData.name
                                    Price = BigDecimalUtil.double2Fen(rechargeData.price)
                                    Coins = rechargeData.currencyCount
                                    OriginalPrice =
                                        BigDecimalUtil.double2Fen(rechargeData.originalPrice)
                                    Tags = rechargeData.tags
                                    GavingCount = rechargeData.gavingCount
                                    HasGift = rechargeData.hasGift
                                    GiftName = rechargeData.giftName
                                    CoinShortName = coinsData.coinShortName
                                    IsFault = coinsData.IsFault
                                }
                            )
                        }
                    }
                }

                override fun onError(throwable: Throwable) {
                    logFile("KKB 获取充值套餐异常：${throwable.message}")
                }

                override fun onComplete() {
                    logFile("KKB 获取充值套餐结束")
                    kkbClientListener.updateCoinsPackage(rechargePackageList)
                }
            })
        }
    }

    /**
     * 获取所有套餐
     */
    private fun getAllPackage() {
//        businessManager?.getPackageList(object : Observer<BaseResult<GoodsCoinResponse?>> {
//
//            override fun onSubscribe(d: Disposable) {
//                logFile("KKB 所有套餐-开始获取普通套餐列表")
//            }
//
//            override fun onNext(t: BaseResult<GoodsCoinResponse?>) {
//                logFile("KKB 所有套餐-普通套餐列表：${GsonUtil.getInstance()?.toJson(t)}")
//                t.getData()?.let { coinsData ->
//                    coinsData.dataList.forEach { normalData ->
//                        normalPackageList.add(
//                            KkbGoodBean().apply {
//                                PackageType = 1
//                                PackageID = normalData.packageID
//                                PakageName = normalData.pakageName
//                                Price = BigDecimalUtil.double2Fen(normalData.price)
//                                Coins = normalData.coins
//                                Subscript = normalData.subscript?:""
//                            }
//                        )
//                    }
//                }
//            }
//
//            override fun onError(throwable: Throwable) {
//                logFile("KKB 所有套餐-获取普通套餐异常：${throwable.message}")
//            }
//
//            override fun onComplete() {
//                logFile("KKB 所有套餐-获取普通套餐结束")
//                if (devNum.isNullOrEmpty()){
//                    kkbClientListener.updateCoinsPackage(normalPackageList)
//                }else{
//                    businessManager?.getRechargeList(devNum!!, object : Observer<BaseResult<RechargeGoodsData?>> {
//
//                        override fun onSubscribe(d: Disposable) {
//                            logFile("KKB 所有套餐-开始获取充值套餐列表")
//                        }
//
//                        override fun onNext(t: BaseResult<RechargeGoodsData?>) {
//                            logFile("KKB 所有套餐-充值套餐列表：${GsonUtil.getInstance()?.toJson(t)}")
//                            t.getData()?.let { coinsData ->
//                                coinsData.data.forEach { rechargeData ->
//                                    rechargePackageList.add(
//                                        KkbGoodBean().apply {
//                                            PackageType = 2
//                                            PackageID = rechargeData.iD
//                                            PakageName = rechargeData.name
//                                            Price = BigDecimalUtil.double2Fen(rechargeData.price)
//                                            Coins = rechargeData.currencyCount
//                                            OriginalPrice = BigDecimalUtil.double2Fen(rechargeData.originalPrice)
//                                            Tags = rechargeData.tags
//                                            GavingCount = rechargeData.gavingCount
//                                            HasGift = rechargeData.hasGift
//                                            GiftName = rechargeData.giftName?:""
//                                            CoinShortName = coinsData.coinShortName
//                                            IsFault = coinsData.IsFault
//                                        }
//                                    )
//                                }
//                            }
//                        }
//
//                        override fun onError(throwable: Throwable) {
//                            logFile("KKB 所有套餐-获取充值套餐异常：${throwable.message}")
//                        }
//
//                        override fun onComplete() {
//                            logFile("KKB 所有套餐-获取充值套餐结束")
//                            val result = mutableListOf<KkbGoodBean>()
//                            if (normalPackageList.isNotEmpty()){
//                                result.addAll(normalPackageList)
//                            }
//                            if (rechargePackageList.isNotEmpty()){
//                                result.addAll(rechargePackageList)
//                            }
//                            kkbClientListener.updateCoinsPackage(result)
//                        }
//                    })
//                }
//            }
//        })
    }

    /**
     * 获取配置信息，信息包含纸钞购币套餐
     */
    fun getConfig() {
        businessManager?.getConfig(object : Observer<BaseResult<KkbGetPayCoinData?>> {

            override fun onSubscribe(d: io.reactivex.disposables.Disposable) {
                logFile("KKB 开始获取配置")
            }

            override fun onNext(t: BaseResult<KkbGetPayCoinData?>) {
                logFile("KKB 配置信息：${GsonUtil.getInstance()?.toJson(t)}")
                t.data?.let { payCoinData ->
                    kkbClientListener.updateConfig(payCoinData)
                }
            }

            override fun onError(throwable: Throwable) {
                logFile("KKB 获取配置信息异常：${throwable.message}")
            }

            override fun onComplete() {
                logFile("KKB 获取配置信息结束")
            }
        })
    }

    /**
     * 上报现金订单
     * @param repCashData 订单数据
     */
    fun repCashData(repCashData: RepCashDataBean) {
        businessManager?.repCashData(repCashData, object : Observer<BaseResult<Any?>> {
            override fun onSubscribe(d: Disposable) {
                logFile("KKB 开始上报现金订单")
            }

            override fun onError(e: Throwable) {
                logFile("KKB 上报现金订单异常：${e.message}")
            }

            override fun onComplete() {
                logFile("KKB 上报现金订单结束")
            }

            override fun onNext(t: BaseResult<Any?>) {
                logFile("KKB 上报现金订单完成：${GsonUtil.getInstance()?.toJson(t)}")

            }
        })
    }

    fun placeCashOrder(buyPackage: KkbBuyPackageBean) {
        if (devNum.isNullOrEmpty() || mchIdentity.isNullOrEmpty()) return

        val paramMap: MutableMap<String?, Any> = mutableMapOf()
        with(buyPackage) {
            paramMap["mchIdentity"] = mchIdentity!!
            paramMap["deviceCode"] = devNum!!
            paramMap["type"] = type
            paramMap["transId"] = parseTransId(transId)
            paramMap["totalPriceCent"] = totalPriceCent
            paramMap["totalCount"] = totalCount
            paramMap["payType"] = payType
            payMoneyCent?.let { paramMap["payMoneyCent"] = it }
        }

        businessManager?.placeOrder(paramMap, object : Observer<BaseResult<KkbBuyPackageResp?>> {
            var resp: KkbBuyPackageResp? = null
            var transId = ""
            override fun onSubscribe(d: Disposable) {
                logFile("KKB 开始现金下单请求1：${GsonUtil.getInstance()?.toJson(buyPackage)}")
                transId = parseTransId(buyPackage.transId)
            }

            override fun onError(e: Throwable) {
                logFile("KKB 现金下单异常：${e.message}")
                onComplete()
            }

            override fun onComplete() {
                logFile("KKB 现金下单结束")
                resp?.let { respData ->
                    logFile("KKB 现金下单数据 transid=$transId orderid=${respData.orderno} ordernumber=${respData.orderno}")
                    kkbClientListener.onPlaceCashOrder(
                        transId,
                        respData.orderno,
                        respData.orderno,
                        paramMap["packageId"]?.toString() ?: "",
                        paramMap["TotalCount"].toString(),
                        paramMap["TotalPriceCent"].toString()
                    )
                }
            }

            override fun onNext(t: BaseResult<KkbBuyPackageResp?>) {
                logFile("KKB 现金下单完成：${GsonUtil.getInstance()?.toJson(t)}")
                resp = t.data
            }
        })
    }

    /**
     * 反扫支付二维码下单
     */
    fun placeOrder(buyPackage: KkbBuyPackageBean) {
        if (devNum.isNullOrEmpty() || mchIdentity.isNullOrEmpty()) return

        val paramMap: MutableMap<String?, Any> = mutableMapOf()
        with(buyPackage) {
            paramMap["mchIdentity"] = mchIdentity!!
            paramMap["deviceCode"] = devNum!!
            paramMap["type"] = type
            paramMap["transId"] = parseTransId(transId)
            paramMap["totalPriceCent"] = totalPriceCent
            paramMap["totalCount"] = totalCount
            paramMap["payType"] = payType
            packageId?.let { paramMap["packageId"] = it }
            payMoneyCent?.let { paramMap["payMoneyCent"] = it }
            payCode?.let { paramMap["payCode"] = it }
        }

        var isComplete = false
        var orderNo = ""

        businessManager?.placeOrder(paramMap, object : Observer<BaseResult<KkbBuyPackageResp?>> {
            var resp: KkbBuyPackageResp? = null
            var transId = ""
            override fun onSubscribe(d: Disposable) {
                logFile("KKB 开始反扫支付码下单：${GsonUtil.getInstance()?.toJson(buyPackage)}")
                transId = parseTransId(buyPackage.transId)
            }

            override fun onError(e: Throwable) {
                logFile("KKB 反扫支付码下单异常：${e.message}")
                onComplete()
            }

            override fun onComplete() {
                logFile("KKB 反扫支付码下单结束")
                resp?.let { respData ->
                    logFile("KKB 查询订单 transid=$transId orderid=${respData.orderno} ordernumber=${respData.orderno}")
                    kkbClientListener.onPlaceOrder(
                        transId,
                        respData.orderno,
                        respData.orderno,
                        paramMap["packageId"]?.toString() ?: "",
                        paramMap["totalCount"].toString(),
                        paramMap["totalPriceCent"].toString()
                    )
                    orderNo = respData.orderno
                }
                isComplete = true
            }

            override fun onNext(t: BaseResult<KkbBuyPackageResp?>) {
                logFile("KKB 反扫支付码下单完成：${GsonUtil.getInstance()?.toJson(t)}")
                resp = t.data
            }
        })

        scope.launch {
            do {
                delay(1000)
            } while (!isComplete)
            if (orderNo.isNotEmpty()) {
                queryPlaceOrder(orderNo)
            }
        }
    }

    /**
     * 获取消费二维码
     * @param goodId 套餐id
     * @param type 0-套餐购买二维码 1-设备二维码
     */
    fun getConsumptionCode(goodId: String, type: Int) {
        businessManager?.getConsumptionCode(object : Observer<BaseResult<GetPayQrCodeData?>> {
            var gid = ""
            var resp: GetPayQrCodeData? = null
            override fun onSubscribe(d: Disposable) {
                logFile("KKB 开始获取消费二维码")
                gid = goodId
            }

            override fun onError(e: Throwable) {
                logFile("KKB 获取消费二维码异常：${e.message}")
                onComplete()
            }

            override fun onComplete() {
                logFile("KKB 获取消费二维码结束")
                resp?.let {
                    when (type) {
                        0 -> {
                            val qrCode =
                                if (it.QRCode.isNotEmpty()) "${it.QRCode}/?tt=2&bi=$gid&type=5&number=$devNum" else it.QRCode
                            kkbClientListener.showBuyConsumptionCode(qrCode)
                        }

                        else -> kkbClientListener.showDevConsumptionCode(it.QRCode)
                    }

                }
            }

            override fun onNext(t: BaseResult<GetPayQrCodeData?>) {
                logFile("KKB 获取消费二维码完成：${GsonUtil.getInstance()?.toJson(t)}")
                resp = t.data
            }
        })
    }

    /**
     * 上报出币结果(mqtt)
     * @param responseCode 状态码 0-出币成功 1-出币失败
     * @param transId 事务id（订单id）
     */
    fun repMqExtractCoinResult(responseCode: Int, transId: String) {
//        deviceManager?.repExtractCoinResult(responseCode, transId)
        extractCoinResult = responseCode
    }

    /**
     * 上报出币结果
     * @param responseCode 状态码 0-出币成功 1-出币失败
     * @param transId 事务id（订单id）
     */
    fun repMqExtractCoinResult(
        realOutCoins: Long,
        needOutCoins: Long,
        result: Int,
        balance: Long,
        orderId: String,
        transId: String,
    ) {
        if (devNum.isNullOrEmpty()) return

        val paramMap: MutableMap<String?, Any> = mutableMapOf()
        paramMap["deviceCode"] = devNum!!
        paramMap["orderno"] = orderId
        paramMap["shouldCount"] = needOutCoins
        paramMap["realCount"] = realOutCoins
        if (result == 1) paramMap["note"] = "出币失败"
        paramMap["deviceBalance"] = balance

        businessManager?.repMqOutCoinResult(paramMap, object : Observer<BaseResult<Any?>> {
            override fun onSubscribe(d: Disposable) {
                logFile("KKB 开始上报MQ出币结果")
            }

            override fun onError(e: Throwable) {
                logFile("KKB 上报MQ出币结果异常：${e.message}")
                onComplete()
            }

            override fun onComplete() {
                logFile("KKB 上报MQ出币结果结束")
            }

            override fun onNext(t: BaseResult<Any?>) {
                logFile("KKB 上报MQ出币结果完成：${GsonUtil.getInstance()?.toJson(t)}")
            }
        })
    }

    /**
     * 上报现金出币结果（下单并上报结果）
     */
    fun repCashResult(
        money: Long,
        realOutCoins: Long,
        needOutCoins: Long,
        result: Int,
        balance: Long,
        orderId: String,
    ) {
        if (devNum.isNullOrEmpty() || mchIdentity.isNullOrEmpty()) return

        val job = scope.launch(Dispatchers.IO) {
            var cashOrderNo = ""

            val placeCashMap: MutableMap<String?, Any> = mutableMapOf()
            placeCashMap["mchIdentity"] = mchIdentity!!
            placeCashMap["deviceCode"] = devNum!!
            placeCashMap["type"] = when (com.sy.simpleegg.config.Config.PRODUCT_TYPE) {
                ProductType.CURRENCY -> 2
                ProductType.BEAD -> 1
            }
            placeCashMap["transId"] =
                if (orderId.length > 32 && orderId.contains("-")) orderId.replace(
                    "-",
                    ""
                ) else orderId
            placeCashMap["totalPriceCent"] = money
            placeCashMap["totalCount"] = needOutCoins
            placeCashMap["payType"] = 3
            placeCashMap["payMoneyCent"] = money

            val startTime = System.currentTimeMillis()
            val interval = 1000L
            var useTime = 0L
            val overTime = 58 * 1000L
            var placeOrderResult = -1//1--未支付，2--正在支付，3--支付完成，4--已取消 99-请求异常

            do {
                businessManager?.placeOrder(
                    placeCashMap,
                    object : Observer<BaseResult<KkbBuyPackageResp?>> {
                        var resp: KkbBuyPackageResp? = null
                        var transId = ""
                        override fun onSubscribe(d: Disposable) {
                            placeOrderResult = -1
                            logFile(
                                "KKB 开始现金下单请求2：${
                                    GsonUtil.getInstance()?.toJson(placeCashMap)
                                }"
                            )
                            transId =
                                if (orderId.length > 32 && orderId.contains("-")) orderId.replace(
                                    "-",
                                    ""
                                ) else orderId
                        }

                        override fun onError(e: Throwable) {
                            logFile("KKB 现金下单异常：${e.message}")
                            useTime = System.currentTimeMillis() - startTime + interval
                            placeOrderResult = 0
                            onComplete()
                        }

                        override fun onComplete() {
                            logFile("KKB 现金下单结束")
                            resp?.let { respData ->
                                logFile("KKB 现金下单数据 transid=$transId orderid=${respData.orderno} ordernumber=${respData.orderno}")
                                cashOrderNo = respData.orderno
                                placeOrderResult = 1
                            }
                        }

                        override fun onNext(t: BaseResult<KkbBuyPackageResp?>) {
                            logFile("KKB 现金下单完成：${GsonUtil.getInstance()?.toJson(t)}")
                            resp = t.data
                        }
                    })

                while (placeOrderResult == -1) {
                    delay(interval)
                }

            } while (cashOrderNo.isEmpty() && useTime < overTime)

            if (cashOrderNo.isEmpty()) return@launch

            val paramMap: MutableMap<String?, Any> = mutableMapOf()
            paramMap["deviceCode"] = devNum!!
            paramMap["orderno"] = cashOrderNo
            paramMap["shouldCount"] = needOutCoins
            paramMap["realCount"] = realOutCoins
            if (result == 1) paramMap["note"] = "出币失败"
            paramMap["deviceBalance"] = balance

            businessManager?.repMqOutCoinResult(paramMap, object : Observer<BaseResult<Any?>> {
                override fun onSubscribe(d: Disposable) {
                    logFile("KKB 开始上报出币结果：${GsonUtil.getInstance()?.toJson(paramMap)}")
                }

                override fun onError(e: Throwable) {
                    logFile("KKB 上报出币结果异常：${e.message}")
                    onComplete()
                }

                override fun onComplete() {
                    logFile("KKB 上报出币结果结束")
                }

                override fun onNext(t: BaseResult<Any?>) {
                    logFile("KKB 上报出币结果完成：${GsonUtil.getInstance()?.toJson(t)}")
                }
            })
        }
    }

    /**
     * 上报非MQ出币结果
     * @param responseCode 状态码 0-出币成功 1-出币失败
     * @param transId 事务id（订单id）
     */
    fun repNotMqExtractCoinResult(result: Int, orderId: String, msg: String) {
        businessManager?.repNotMqOutCoinResult(
            result,
            orderId,
            msg,
            object : Observer<BaseResult<Any?>> {
                override fun onSubscribe(d: Disposable) {
                    logFile("KKB 开始上报非MQ出币结果")
                }

                override fun onError(e: Throwable) {
                    logFile("KKB 上报非MQ出币结果异常：${e.message}")
                    onComplete()
                }

                override fun onComplete() {
                    logFile("KKB 上报非MQ出币结果结束")
                }

                override fun onNext(t: BaseResult<Any?>) {
                    logFile("KKB 上报非MQ出币结果完成：${GsonUtil.getInstance()?.toJson(t)}")
                }
            })
    }

    /**
     * 查询下单支付结果
     */
    private fun queryPlaceOrder(orderId: String) {
        if (devNum.isNullOrEmpty()) return
        val job = scope.launch(Dispatchers.IO) {
            val startTime = System.currentTimeMillis()
            val interval = 1000L
            var useTime = 0L
            val overTime = 58 * 1000L
            var result = -1//1--未支付，2--正在支付，3--支付完成，4--已取消 99-请求异常

            val paramMap: MutableMap<String?, Any> = mutableMapOf()
            paramMap["deviceCode"] = devNum!!
            paramMap["orderno"] = orderId

            do {
                delay(interval)
                businessManager?.getPayResult(paramMap, object : Observer<BaseResult<PayResult?>> {
                    override fun onSubscribe(d: Disposable) {
                        logFile("KKB 开始查询下单支付结果")
                    }

                    override fun onError(e: Throwable) {
                        logFile("KKB 查询下单支付结果异常：${e.message}")
                        result = 99
                        onComplete()
                    }

                    override fun onComplete() {
                        logFile("KKB 查询下单支付结果结束")
                        useTime = System.currentTimeMillis() - startTime + interval
                    }

                    override fun onNext(t: BaseResult<PayResult?>) {
                        logFile("KKB 查询下单支付结果完成：${GsonUtil.getInstance()?.toJson(t)}")
                        result = t.data?.status ?: 4
                    }
                })

                while (result == -1) {
                    delay(interval)
                }

            } while (useTime < overTime && result <= 2)

            kkbClientListener.placeOrderResult(orderId, result == 3)
            jobMap.remove(orderId)
        }

        jobMap[orderId] = job
    }

    /**
     * 移除查询订单支付结果任务
     * @param transId 事务id
     */
    fun removeQueryOrder(transId: String) {
        jobMap[transId]?.let { job ->
            job.cancel()
            jobMap.remove(transId)
        }
    }

    fun getLoginCode() {
//        testLogin()
//        return
        if (devNum.isNullOrEmpty() || mchIdentity.isNullOrEmpty()) return
        val paramMap: MutableMap<String?, Any> = mutableMapOf()
        paramMap["mchIdentity"] = mchIdentity!!
        paramMap["deviceCode"] = devNum!!
        businessManager?.getMemberLoginCode(
            paramMap,
            object : Observer<BaseResult<GetMemberLoginQrCode?>> {
                var resp: GetMemberLoginQrCode? = null
                override fun onSubscribe(d: Disposable) {
                    logFile("KKB 开始获取登录二维码")

                }

                override fun onError(e: Throwable) {
                    logFile("KKB 获取登录二维码异常：${e.message}")
                    onComplete()
                }

                override fun onComplete() {
                    logFile("KKB 获取登录二维码结束")
                    resp?.let {
                        kkbClientListener.getLoginCode(it.qrcode, it.loginFlag)
                        queryLgLogin(it.loginFlag)
                    }
                }

                override fun onNext(t: BaseResult<GetMemberLoginQrCode?>) {
                    logFile("KKB 获取登录二维码完成：${GsonUtil.getInstance()?.toJson(t)}")
                    resp = t.data
                }
            })
    }

    /**
     * 查询会员扫码登录结果
     * @param transId 登录二维码返回的事务id
     */
    private fun queryLgLogin(transId: String) {
        if (devNum.isNullOrEmpty()) return

        loginJob?.cancel()

        loginJob = scope.launch(Dispatchers.IO) {
            loginLoop = true
            val tid = transId
            var loginStatus = -1//0-等待登录（继续轮询） 1-登录成功 2-其他异常
            var useTime = 0L
            val startTime = System.currentTimeMillis()
            val interval = 1000L
            val overTime = 58 * 1000L
            var resp: KkbQrCodeMemberInfoResponse? = null
            var openId = ""
            var openIdResult = -1

            val paramMap: MutableMap<String?, Any> = mutableMapOf()
            paramMap["loginFlag"] = transId
            paramMap["deviceCode"] = devNum!!
            paramMap["mchIdentity"] = mchIdentity!!

            do {
                delay(interval)
                businessManager?.queryOpenId(
                    paramMap,
                    object : Observer<BaseResult<KkbOpenIdResponse?>> {
                        override fun onSubscribe(d: Disposable) {
                            logFile("KKB 开始查询会员OpenId loginFlag=$transId")
                            openIdResult = -1
                        }

                        override fun onError(e: Throwable) {
                            logFile("KKB 查询会员OpenId异常：${e.message}")
                            openIdResult = 0
//                                try {
//                                    e.message?.let {
//                                        GsonUtil.getInstance()?.fromJson<LoginStatus>(
//                                            it,
//                                            object : TypeToken<LoginStatus?>() {}.type
//                                        )?.run {
//                                            if (status == -1) {
//                                                logFile("KKB 查询会员未登录：$msg")
//                                                0
//                                            } else {
//                                                2
//                                            }
//                                        } ?: 2
//                                    } ?: 2
//                                } catch (e: Exception) {
//                                    e.printStackTrace()
//                                    2
//                                }
                        }

                        override fun onComplete() {
                            logFile("KKB 查询会员OpenId结束")
                        }

                        override fun onNext(t: BaseResult<KkbOpenIdResponse?>) {
                            logFile("KKB 查询会员扫码登录完成：${GsonUtil.getInstance()?.toJson(t)}")
                            openIdResult = 1
                            openId = t.data?.kkbOpenId ?: ""
                        }
                    })

                while (openIdResult == -1) {
                    delay(interval)
                }

            } while (openIdResult == 0)

            if (openId.isEmpty()) return@launch

            val memberParamMap: MutableMap<String?, Any> = mutableMapOf()
            memberParamMap["kkbOpenId"] = openId

            do {
                delay(interval)
                businessManager?.queryLgLogin(
                    memberParamMap,
                    object : Observer<BaseResult<KkbQrCodeMemberInfoResponse?>> {
                        override fun onSubscribe(d: Disposable) {
                            logFile("KKB 开始查询会员信息 transId=$transId")
                            loginStatus = -1
                        }

                        override fun onError(e: Throwable) {
                            logFile("KKB 查询会员扫码信息异常：${e.message}")
                            loginStatus = 0
                            onComplete()
                        }

                        override fun onComplete() {
                            logFile("KKB 查询会员扫码信息结束")
                            useTime = System.currentTimeMillis() - startTime + interval
                            if (loginStatus == 1) {
                                loginLoop = false
                                resp?.let {
                                    kkbClientListener.onLgLogin(it)
                                }
                            }
                        }

                        override fun onNext(t: BaseResult<KkbQrCodeMemberInfoResponse?>) {
                            logFile("KKB 查询会员扫码信息完成：${GsonUtil.getInstance()?.toJson(t)}")
                            resp = t.data
                            loginStatus = 1
                        }
                    })

                while (loginStatus == -1) {
                    delay(interval)
                }

            } while (loginLoop && loginStatus == 0 && useTime < overTime)
        }
    }

    /**
     * 移除查询会员扫码登录任务
     */
    fun removeQueryLgLogin() {
        loginLoop = false
        loginJob?.cancel()
    }

    /**
     * 会员存币
     * @param leaguerId 会员ID
     * @param num 存币数
     * @param remark 备注
     * @param transId 事务ID
     */
    fun repSaveCoinsData(memberId: String, num: Long, remark: String, transId: String) {
        if (devNum.isNullOrEmpty() || mchIdentity.isNullOrEmpty()) return

        val paramMap: MutableMap<String?, Any> = mutableMapOf()
        paramMap["deviceCode"] = devNum!!
        paramMap["mchIdentity"] = mchIdentity!!
        paramMap["type"] = when (com.sy.simpleegg.config.Config.PRODUCT_TYPE) {
            ProductType.CURRENCY -> 2
            ProductType.BEAD -> 1
        }
        paramMap["memberId"] = memberId
        paramMap["transId"] = parseTransId(transId)
        paramMap["totalCount"] = num

        businessManager?.repSaveCoinsData(paramMap, object : Observer<BaseResult<SaveCoinResult?>> {
            var resp: SaveCoinResult? = null
            override fun onSubscribe(d: Disposable) {
                logFile("KKB 开始上报会员存币数据")

            }

            override fun onError(e: Throwable) {
                logFile("KKB 上报会员存币数据异常：${e.message}")
                onComplete()
            }

            override fun onComplete() {
                logFile("KKB 上报会员存币数据结束")
                resp?.let {
                    kkbClientListener.saveCoinsFinish(it.balanceCount)
                }
            }

            override fun onNext(t: BaseResult<SaveCoinResult?>) {
                logFile("KKB 上报会员存币数据完成：${GsonUtil.getInstance()?.toJson(t)}")
                resp = t.data
            }
        })
    }

    /**
     * 会员提取
     * @param leaguerId 会员ID
     * @param num 存币数
     * @param remark 备注
     * @param transId 事务ID
     */
    fun repConsumeCoinsData(memberId: String, num: Long, remark: String, transId: String) {
        if (devNum.isNullOrEmpty()) return

        val paramMap: MutableMap<String?, Any> = mutableMapOf()
        paramMap["mchIdentity"] = mchIdentity
        paramMap["deviceCode"] = devNum!!
        paramMap["type"] = when (com.sy.simpleegg.config.Config.PRODUCT_TYPE) {
            ProductType.CURRENCY -> 2
            ProductType.BEAD -> 1
        }
        paramMap["memberId"] = memberId
        paramMap["transId"] = parseTransId(transId)
        paramMap["totalCount"] = num

        businessManager?.repConsumeCoinsData(
            paramMap,
            object : Observer<BaseResult<ConsumeCoinResult?>> {
                var resp: ConsumeCoinResult? = null
                var msg: String? = null
                var status: Long = -1
                override fun onSubscribe(d: Disposable) {
                    logFile("KKB 开始上报会员取币数据")

                }

                override fun onError(e: Throwable) {
                    logFile("KKB 上报会员取币数据异常：${e.message}")
                    msg = e.message
                    onComplete()
                }

                override fun onComplete() {
                    logFile("KKB 上报会员取币数据结束")
                    kkbClientListener.consumeCoinsFinish(
                        status == 0L,
                        msg,
                        resp?.memberId,
                        resp?.balanceCount
                    )
                }

                override fun onNext(t: BaseResult<ConsumeCoinResult?>) {
                    logFile("KKB 上报会员取币数据完成：${GsonUtil.getInstance()?.toJson(t)}")
                    resp = t.data
                    msg = t.msg
                    status = t.status
                }
            })
    }

    /**
     * 上报核销数据
     * @param codeData 核销码
     * @param channel 团购平台
     * @param transId 事务id
     */
    fun repWriteOffData(codeData: String, channel: String, amount: Long, transId: String = "") {
        devNum?.let {
            businessManager?.repWriteOffData(
                codeData,
                transId,
                amount,
                channel,
                it,
                false,
                2,
                object : Observer<BaseResult<KkbChannelWaitOffData?>> {
                    var resp: KkbChannelWaitOffData? = null
                    override fun onSubscribe(d: Disposable) {
                        logFile("KKB 开始上报核销数据")
                    }

                    override fun onError(e: Throwable) {
                        logFile("KKB 上报核销数据异常：${e.message}")
                        onComplete()
                    }

                    override fun onComplete() {
                        logFile("KKB 上报核销数据结束")
                        resp?.let {
                            kkbClientListener.writeOffResult(it)
                        }
                    }

                    override fun onNext(t: BaseResult<KkbChannelWaitOffData?>) {
                        logFile("KKB 上报核销数据完成：${GsonUtil.getInstance()?.toJson(t)}")
                        resp = t.data
                    }
                })
        }
    }

    private fun parseTransId(tid: String): String {
        return if (tid.length > 32 && tid.contains("-")) {
            tid.replace("-", "")
        } else if (tid.length > 32) {
            tid.substring(0, 32)
        } else {
            tid
        }
    }

    private fun testLogin() {
        kkbClientListener.onLgLogin(
            KkbQrCodeMemberInfoResponse(
                "",
                "",
                "062111",
                "test",
                "",
                100,
                100,
                100,
                100,
                100,
                "",
                "",
                "",
                100,

                )
        )
    }

    interface KkbClientListener {
        fun registerFailed(errorCode: Long, errorMsg: String?)

        fun needUpdate(vararg updateAddress: String?)

        fun bindStatus(isSuccess: Boolean, deviceNumber: String?)

        fun onError(type: String?, errorCode: Long, msg: String?)

        fun deviceBinding(devNumber: String)

        fun deviceUnBinding()

        fun deviceReBoot()

        fun extractCoin(isMq: Boolean, coins: String, money: String, orderId: String)

        fun getDeviceSetting(dataJson: String?)

        fun setDeviceSetting(dataJson: String?)

        fun changeCashPackage()

        fun updateOrder(
            orderId: String?,
            transactionId: String?,
            deviceStatus: Int,
            remark: String?,
        )

        fun deviceStatues(status: Int)

        fun loginComplete()

        fun updateCoinsPackage(coinsPackage: MutableList<KkbGoodBean>)

        fun updateConfig(configData: KkbGetPayCoinData)

        fun showPayCode(transId: String, orderId: String, orderNumber: String, codeData: String)

        fun onPlaceOrder(
            transId: String,
            orderId: String,
            orderNumber: String,
            goodId: String,
            coins: String,
            money: String,
        )

        fun onPlaceCashOrder(
            transId: String,
            orderId: String,
            orderNumber: String,
            goodId: String,
            coins: String,
            money: String,
        )

        fun placeOrderResult(transId: String, paySuccess: Boolean)

        fun showBuyConsumptionCode(codeData: String)

        fun showDevConsumptionCode(codeData: String)

        fun getLoginCode(codeData: String, transId: String)

        fun onLgLogin(loginMemberInfo: KkbQrCodeMemberInfoResponse)

        fun saveCoinsFinish(balance: Long)

        fun consumeCoinsFinish(success: Boolean, errMsg: String?, memberId: String?, balance: Long?)

        fun writeOffResult(writeOffResult: KkbChannelWaitOffData)
    }


}